home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / RCS / tcpInput.c,v < prev    next >
Encoding:
Text File  |  1991-10-25  |  59.8 KB  |  2,438 lines

  1. head     1.14;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.14
  10. date     91.10.25.10.47.56;  author mottsmth;  state Exp;
  11. branches ;
  12. next     1.13;
  13.  
  14. 1.13
  15. date     89.07.23.17.34.29;  author nelson;  state Exp;
  16. branches ;
  17. next     1.12;
  18.  
  19. 1.12
  20. date     89.05.19.14.40.24;  author douglis;  state Exp;
  21. branches ;
  22. next     1.11;
  23.  
  24. 1.11
  25. date     89.03.23.09.53.35;  author brent;  state Exp;
  26. branches ;
  27. next     1.10;
  28.  
  29. 1.10
  30. date     89.02.21.10.08.13;  author brent;  state Exp;
  31. branches ;
  32. next     1.9;
  33.  
  34. 1.9
  35. date     88.10.17.09.08.28;  author ouster;  state Exp;
  36. branches ;
  37. next     1.8;
  38.  
  39. 1.8
  40. date     88.09.22.14.29.13;  author mendel;  state Exp;
  41. branches ;
  42. next     1.7;
  43.  
  44. 1.7
  45. date     88.09.15.09.32.56;  author mendel;  state Exp;
  46. branches ;
  47. next     1.6;
  48.  
  49. 1.6
  50. date     88.08.16.11.19.08;  author mendel;  state Exp;
  51. branches ;
  52. next     1.5;
  53.  
  54. 1.5
  55. date     88.05.31.14.10.10;  author mendel;  state Exp;
  56. branches ;
  57. next     1.4;
  58.  
  59. 1.4
  60. date     88.05.15.19.29.46;  author andrew;  state Exp;
  61. branches ;
  62. next     1.3;
  63.  
  64. 1.3
  65. date     88.05.02.13.54.01;  author brent;  state Exp;
  66. branches ;
  67. next     1.2;
  68.  
  69. 1.2
  70. date     88.04.27.09.10.07;  author brent;  state Exp;
  71. branches ;
  72. next     1.1;
  73.  
  74. 1.1
  75. date     87.12.12.16.20.42;  author andrew;  state Exp;
  76. branches ;
  77. next     ;
  78.  
  79.  
  80. desc
  81. @@
  82.  
  83.  
  84. 1.14
  85. log
  86. @Fixed case value in ProcessOptions
  87. @
  88. text
  89. @/* 
  90.  * tcpInput.c --
  91.  *
  92.  *    Routines to handle TCP packets. The packet is examined for
  93.  *    proper format before the data are saved in a socket's recv buffer.
  94.  *
  95.  *    The algorithms in this file are based on the functional specification
  96.  *    of the Transmission Control Protocol in RFC793 (Sept. 1981).
  97.  *
  98.  *    Security and precedence checks are not performed on the packet.
  99.  *
  100.  *     Based on the following 4.3BSD file:
  101.  *    "@@(#)tcp_input.c 7.18 (Berkeley) 5/14/88"
  102.  *
  103.  * Copyright 1987 Regents of the University of California
  104.  * All rights reserved.
  105.  * Permission to use, copy, modify, and distribute this
  106.  * software and its documentation for any purpose and without
  107.  * fee is hereby granted, provided that the above copyright
  108.  * notice appear in all copies.  The University of California
  109.  * makes no representations about the suitability of this
  110.  * software for any purpose.  It is provided "as is" without
  111.  * express or implied warranty.
  112.  */
  113.  
  114. #ifndef lint
  115. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpInput.c,v 1.13 89/07/23 17:34:29 nelson Exp Locker: mottsmth $ SPRITE (Berkeley)";
  116. #endif not lint
  117.  
  118.  
  119. #include "sprite.h"
  120. #include "netInet.h"
  121. #include "ipServer.h"
  122. #include "stat.h"
  123. #include "ip.h"
  124. #include "tcp.h"
  125. #include "tcpInt.h"
  126. #include "socket.h"
  127. #include "route.h"
  128.  
  129. #include "list.h"
  130. #include "fs.h"
  131.  
  132. /*
  133.  * Global variables for
  134.  */
  135. int    tcpISS = 0;
  136. int    tcpReXmtThresh = 3;
  137.  
  138. /*
  139.  * Information about data segments on the reassembly queue of a socket's TCB.
  140.  */
  141. typedef struct {
  142.     List_Links        links;        /* Used to chain elements together. */
  143.     Address        data;        /* Ptr to the segment data. */
  144.     Address        base;        /* Ptr to the segment base. This address
  145.                      * is used with free. */
  146.     int            len;        /* Length of the data. */
  147.     unsigned short    flags;        /* TCP header flags of the segment. */
  148.     TCPSeqNum        seqNum;        /* TCP sequence number of the segment.*/
  149. } ReassElement;
  150.  
  151.  
  152. static void    Input();
  153. static void    ProcessOptions();
  154. extern int    TCPCalcMaxSegSize();
  155. static void    CalcFreeSpace();
  156. static unsigned short    Reassemble();
  157.  
  158.  
  159. /*
  160.  *----------------------------------------------------------------------
  161.  *
  162.  * TCP_MemBin --
  163.  *
  164.  *    Bucketize various structures that are dynamically allocated by TCP.
  165.  *
  166.  * Results:
  167.  *    None.
  168.  *
  169.  * Side effects:
  170.  *    Calls Mem_Bin.
  171.  *
  172.  *----------------------------------------------------------------------
  173.  */
  174.  
  175. void
  176. TCP_MemBin()
  177. {
  178.     Mem_Bin(sizeof(ReassElement));
  179.     Mem_Bin(sizeof(TCPControlBlock));
  180.     Mem_Bin(sizeof(TCPConnectInfo));
  181.     Mem_Bin(sizeof(Net_TCPHeader));
  182.     Mem_Bin(TCP_BUF_SIZE);
  183. }
  184.  
  185. /*
  186.  *----------------------------------------------------------------------
  187.  *
  188.  * TCP_Init --
  189.  *
  190.  *    Initialize TCP data structures.
  191.  *
  192.  * Results:
  193.  *    None.
  194.  *
  195.  * Side effects:
  196.  *    A routine is set up to handle TCP packets. The initial send
  197.  *    sequence number is determined.
  198.  *
  199.  *----------------------------------------------------------------------
  200.  */
  201.  
  202. void
  203. TCP_Init(seconds)
  204.     int    seconds;    /* Used to set the initial send sequence #. */
  205. {
  206.     if (ips_Debug) {
  207.     (void) (void) fprintf(stderr, "TCP: sizeof(tcb) = %d\n", 
  208.                 sizeof(TCPControlBlock));
  209.     }
  210.     tcpISS = seconds;
  211.     IP_SetProtocolHandler(NET_IP_PROTOCOL_TCP, Input);
  212.     TCPTimerInit();
  213. }
  214.  
  215.  
  216. /*
  217.  *----------------------------------------------------------------------
  218.  *
  219.  * Input --
  220.  *
  221.  *    This routine accepts IP datagrams and processes data for
  222.  *    this protocol.
  223.  *
  224.  *    TCP input routine, follows pages 65-76 of the
  225.  *    protocol specification dated September, 1981 very closely.
  226.  *
  227.  * Results:
  228.  *    None.
  229.  *
  230.  * Side effects:
  231.  *    Many.
  232.  *
  233.  *----------------------------------------------------------------------
  234.  */
  235.  
  236. /*ARGSUSED*/
  237. static void
  238. Input(netID, packetPtr)
  239.     Rte_NetID    netID;        /* Which network the packet came from. */
  240.     IPS_Packet    *packetPtr;    /* Packet descriptor. */
  241. {
  242.     register Net_TCPHeader    *tcpHdrPtr;
  243.     register Net_IPHeader    *ipHdrPtr;
  244.     register TCPControlBlock    *tcbPtr;
  245.     register unsigned short    headerFlags;
  246.     int                dataLen;
  247.     int                offset;
  248.     Address            data;
  249.     Net_TCPHeader        saveHeader;
  250.     Sock_InfoPtr        sockPtr;
  251.     TCPState             oldState;
  252.     int             toDrop;
  253.     int             acked;
  254.     Boolean            ourFinIsAcked;
  255.     int             needOutput = FALSE;
  256.     int                iss = 0;
  257.     Boolean            freePacket = TRUE;
  258.  
  259.     stats.tcp.recv.total++;
  260.  
  261.     ipHdrPtr  = packetPtr->ipPtr;
  262.     tcpHdrPtr =(Net_TCPHeader *) ((Address) ipHdrPtr + (ipHdrPtr->headerLen*4));
  263.     dataLen   = ipHdrPtr->totalLen - (ipHdrPtr->headerLen*4);
  264.     data      = (Address) tcpHdrPtr;
  265.  
  266.     if (dataLen < sizeof(Net_TCPHeader)) {
  267.     stats.tcp.recv.shortLen++;
  268.     free(packetPtr->base);
  269.     return;
  270.     }
  271.  
  272.     /*
  273.      * Make sure the shecksum is valid.
  274.      */
  275.     {
  276.     Net_IPPseudoHdr        pseudoHdr;
  277.     unsigned short        sum;
  278.  
  279.     /*
  280.      * The checksum is computed for the IP "pseudo-header" and
  281.      * the TCP header and data. When the TCP checksum was calculated,
  282.      * the checksum field in the header was set to zero. When we 
  283.      * recalculate the value, we don't zero the field so the computed 
  284.      * value should be zero if the packet didn't get garbled.
  285.      */
  286.     pseudoHdr.source    = ipHdrPtr->source;
  287.     pseudoHdr.dest        = ipHdrPtr->dest;
  288.     pseudoHdr.zero        = 0;
  289.     pseudoHdr.protocol    = ipHdrPtr->protocol;
  290.     pseudoHdr.len        = Net_HostToNetShort((unsigned short)dataLen);
  291.     sum = Net_InetChecksum2(dataLen, (Address) tcpHdrPtr, &pseudoHdr);
  292.     if (sum != 0) {
  293.         if (ips_Debug) {
  294.         (void) fprintf(stderr, "TCP: checksum != 0 (%x)\n", sum);
  295.         }
  296.  
  297.         stats.tcp.recv.badChecksum++;
  298.         free(packetPtr->base);
  299.         return;
  300.     }
  301.     }
  302.  
  303.     /*
  304.      * Make sure the data offset is valid.
  305.      */
  306.  
  307.     offset = tcpHdrPtr->dataOffset * 4;
  308.     if ((offset < sizeof(Net_TCPHeader)) || (offset > dataLen)) {
  309.     stats.tcp.recv.badOffset++;
  310.     if (ips_Debug) {
  311.         (void) fprintf(stderr, "TCP Input: bad offset (%d)\n", offset);
  312.     }
  313.     free(packetPtr->base);
  314.     return;
  315.     }
  316.     dataLen -= offset;
  317.     data    += offset;
  318.  
  319.     /*
  320.      * The packetPtr must contain current values of the data length and
  321.      * buffer address. Whenever packetPtr is used below, it will be
  322.      * updated with the latest values of dataLen and data.
  323.      */
  324.     packetPtr->dataLen = dataLen;
  325.     packetPtr->data    = data;
  326.  
  327.  
  328.     /*
  329.      * Convert TCP protocol specific fields to host format.
  330.      */
  331. #ifdef notdef
  332.     tcpHdrPtr->srcPort     = Net_NetToHostShort(tcpHdrPtr->srcPort);
  333.     tcpHdrPtr->destPort     = Net_NetToHostShort(tcpHdrPtr->destPort);
  334. #endif
  335.     tcpHdrPtr->window     = Net_NetToHostShort(tcpHdrPtr->window);
  336.     tcpHdrPtr->seqNum     = Net_NetToHostInt(tcpHdrPtr->seqNum);
  337.     tcpHdrPtr->ackNum     = Net_NetToHostInt(tcpHdrPtr->ackNum);
  338.     tcpHdrPtr->urgentOffset = Net_NetToHostShort(tcpHdrPtr->urgentOffset);
  339.     headerFlags = tcpHdrPtr->flags;
  340.  
  341.     if (ips_Debug) {
  342.     (void) fprintf(stderr, 
  343.             "TCP Input: %d bytes <%x,%d> <-- <%x,%d,#%d>\n\t",
  344.             dataLen,
  345.             Net_NetToHostInt(ipHdrPtr->dest), 
  346.             Net_NetToHostShort(tcpHdrPtr->destPort),
  347.             Net_NetToHostInt(ipHdrPtr->source),
  348.             Net_NetToHostShort(tcpHdrPtr->srcPort),
  349.             ipHdrPtr->ident);
  350.     TCPPrintHdrFlags(stderr, headerFlags);
  351.     (void) fprintf(stderr, "  seq=%d,  ack=%d\n",
  352.             tcpHdrPtr->seqNum,tcpHdrPtr->ackNum);
  353.     }
  354.  
  355.     /*
  356.      * Locate socket/tcb info for the segment.
  357.      */
  358.  
  359. findSock:
  360.  
  361.     tcbPtr = (TCPControlBlock *) NULL;
  362.  
  363.     sockPtr = (Sock_InfoPtr) Sock_Match(TCP_PROTO_INDEX, 
  364.             ipHdrPtr->dest, tcpHdrPtr->destPort, 
  365.             ipHdrPtr->source, tcpHdrPtr->srcPort, 
  366.             TRUE);
  367.  
  368.     /*
  369.      * If the state is CLOSED (i.e., TCB does not exist) then
  370.      * all data in the incoming segment is discarded. If the TCB exists
  371.      * but is in the CLOSED state, then it's embryonic so it should
  372.      * do a listen or a connect soon.
  373.      */
  374.     if (sockPtr == (Sock_InfoPtr) NULL) {
  375.     goto dropWithReset;
  376.     }
  377.  
  378.     tcbPtr = TCPSockToTCB(sockPtr);
  379.     if (tcbPtr == (TCPControlBlock *) NULL) {
  380.     goto dropWithReset;
  381.     }
  382.     if (tcbPtr->state == CLOSED) {
  383.     goto drop;
  384.     }
  385.  
  386.     if (Sock_IsOptionSet(sockPtr, NET_OPT_DEBUG)) {
  387.     oldState = tcbPtr->state;
  388.     saveHeader = *tcpHdrPtr;
  389.     }
  390.  
  391.  
  392.  
  393.     /*
  394.      * p. 65
  395.      *
  396.      * If the socket is in the LISTEN state, then ignore the segment if the
  397.      * RESET bit is set.  If the segment contains an ACK, then it is bad --
  398.      * send a RESET to the peer.  If the segment does not contain a SYN, then 
  399.      * it is not interesting and it is dropped.  Don't bother responding if 
  400.      * the destination was a broadcast.  Otherwise initialize 
  401.      * tcbPtr->recv.next, and tcbPtr->recv.initial, select a value for
  402.      * tcbPtr->send.initial, and send a segment with:
  403.      *
  404.      *     <SEQ=ISS><ACK=RECV.NEXT><CTL=SYN,ACK> 
  405.      *
  406.      * Also initialize tcbPtr->send.next to tcbPtr->send.initial+1 and
  407.      * tcbPtr->send.unAck to tcbPtr->send.initial.  Fill in the remote
  408.      * peer address fields if not previously specified.  Enter the
  409.      * SYN_RECEIVED state, and process any other fields of this segment 
  410.      * in this state.
  411.      */
  412.  
  413.     if (tcbPtr->state == LISTEN) {
  414.  
  415.     if (headerFlags & NET_TCP_RST_FLAG) {
  416.         goto drop;
  417.     }
  418.     if (headerFlags & NET_TCP_ACK_FLAG) {
  419.         goto dropWithReset;
  420.     }
  421.     if ((headerFlags & NET_TCP_SYN_FLAG) == 0) {
  422.         goto drop;
  423.     }
  424.     if (Rte_IsBroadcastAddr(ipHdrPtr->dest)) {
  425.         goto drop;
  426.     }
  427.  
  428.     /*
  429.      * Try to create a new socket and TCB. If there's and error then
  430.      * drop the segment.
  431.      */
  432.     sockPtr = TCPCloneConnection(sockPtr, 
  433.             ipHdrPtr->dest, 
  434.             tcpHdrPtr->destPort, ipHdrPtr->source, tcpHdrPtr->srcPort);
  435.     if (sockPtr == (Sock_InfoPtr) NULL) {
  436.         goto drop;
  437.     }
  438.     tcbPtr = TCPSockToTCB(sockPtr);
  439.  
  440.  
  441.     TCPMakeTemplateHdr(sockPtr, tcbPtr);
  442.     if (offset > sizeof(Net_TCPHeader)) {
  443.         ProcessOptions(offset, tcpHdrPtr, tcbPtr);
  444.     }
  445.  
  446.     /*
  447.      * Select the initial send and receive sequence numbers and initialize
  448.      * the other fields.
  449.      */
  450.  
  451.     if (iss != 0) {
  452.         tcbPtr->send.initial = iss;
  453.     } else {
  454.         tcbPtr->send.initial = tcpISS;
  455.     }
  456.     tcpISS += TCP_INIT_SEND_SEQ_INCR/2;
  457.     tcbPtr->recv.initial = tcpHdrPtr->seqNum;
  458.     TCP_SEND_SEQ_INIT(tcbPtr);
  459.     TCP_RECV_SEQ_INIT(tcbPtr);
  460.  
  461.     tcbPtr->flags |= TCP_ACK_NOW;
  462.     tcbPtr->state = SYN_RECEIVED;
  463.     tcbPtr->idle = 0;
  464.     tcbPtr->timer[TCP_TIMER_KEEP_ALIVE] = TCP_KEEP_TIME_INIT;
  465.     CalcFreeSpace(sockPtr, tcbPtr);
  466.     stats.tcp.accepts++;
  467.     goto trimThenUpdateWindow;
  468.  
  469.     } 
  470.  
  471.  
  472.  
  473.     if (offset > sizeof(Net_TCPHeader)) {
  474.     ProcessOptions(offset, tcpHdrPtr, tcbPtr);
  475.     }
  476.  
  477.     /*
  478.      * A segment was received on an active connection.  Reset the idle time 
  479.      * and the keep-alive timer.
  480.      */
  481.     tcbPtr->idle = 0;
  482.     tcbPtr->timer[TCP_TIMER_KEEP_ALIVE] = tcpKeepIdle;
  483.     CalcFreeSpace(sockPtr, tcbPtr);
  484.     
  485.  
  486.  
  487.     if (tcbPtr->state == SYN_SENT) {
  488.  
  489.     /*
  490.      * p. 66
  491.      *
  492.      * If the TCB state is SYN_SENT:
  493.      *    if seg contains an ACK, but not for our SYN, drop the input.
  494.      *    if seg contains a RESET, then drop the connection.
  495.      *    if seg does not contain SYN, then drop it.
  496.      * Otherwise this is an acceptable SYN segment.
  497.      *    1) Initialize tcbPtr->recv.next and tcbPtr->recv.initial
  498.      *    2) If seg contains ack then advance tcbPtr->send.unAck.
  499.      *    3) If SYN has been acked, change to ESTABLISHED state, else
  500.      *    change to the SYN_RCVD state.
  501.      *    4) Arrange for segment to be acked (eventually)
  502.      *    5) Continue processing the rest of the data/controls, 
  503.      *       beginning with the URG bit.
  504.      */
  505.  
  506.     if ((headerFlags & NET_TCP_ACK_FLAG) &&
  507.         (TCP_SEQ_LE(tcpHdrPtr->ackNum, tcbPtr->send.initial) ||
  508.          TCP_SEQ_GT(tcpHdrPtr->ackNum, tcbPtr->send.maxSent))) {
  509.         goto dropWithReset;
  510.     }
  511.  
  512.     if (headerFlags & NET_TCP_RST_FLAG) {
  513.         if (headerFlags & NET_TCP_ACK_FLAG) {
  514.         TCPDropConnection(sockPtr, tcbPtr, 
  515.                     (ReturnStatus)NET_CONNECT_REFUSED);
  516.         tcbPtr = NULL;
  517.         }
  518.         goto drop;
  519.     }
  520.  
  521.     if ((headerFlags & NET_TCP_SYN_FLAG) == 0) {
  522.         goto drop;
  523.     }
  524.  
  525.     if (headerFlags & NET_TCP_ACK_FLAG) {
  526.         tcbPtr->send.unAck = tcpHdrPtr->ackNum;
  527.         if (TCP_SEQ_LT(tcbPtr->send.next, tcbPtr->send.unAck)) {
  528.         tcbPtr->send.next = tcbPtr->send.unAck;
  529.         }
  530.     }
  531.  
  532.     tcbPtr->timer[TCP_TIMER_REXMT] = 0;
  533.     tcbPtr->recv.initial = tcpHdrPtr->seqNum;
  534.     TCP_RECV_SEQ_INIT(tcbPtr);
  535.     tcbPtr->flags |= TCP_ACK_NOW;
  536.  
  537.     if ((headerFlags & NET_TCP_ACK_FLAG) && 
  538.         TCP_SEQ_GT(tcbPtr->send.unAck, tcbPtr->send.initial)) {
  539.  
  540.         stats.tcp.connects++;
  541.         Sock_Connected(sockPtr);
  542.         tcbPtr->state = ESTABLISHED;
  543.         tcbPtr->maxSegSize = MIN(tcbPtr->maxSegSize, 
  544.                         TCPCalcMaxSegSize(tcbPtr));
  545.         packetPtr->data = data;
  546.         packetPtr->dataLen = dataLen;
  547.         (void) Reassemble(sockPtr, tcbPtr, (Net_TCPHeader *)NULL,
  548.                 packetPtr);
  549.         /*
  550.          * If we didn't have to retransmit the SYN, use its round-trip
  551.          * time as our initial smooth rrt and rtt var.
  552.          */
  553.         if (tcbPtr->rtt != 0) {
  554.         tcbPtr->srtt = tcbPtr->rtt << 3;
  555.         tcbPtr->rttvar = tcbPtr->rtt << 1;
  556.         TCP_TIMER_RANGESET(tcbPtr->rxtcur, 
  557.             ((tcbPtr->srtt >> 2) + tcbPtr->rttvar) >> 1,
  558.             TCP_MIN_REXMT_TIME, TCP_MAX_REXMT_TIME);
  559.         tcbPtr->rtt = 0;
  560.         }
  561.     } else {
  562.         tcbPtr->state = SYN_RECEIVED;
  563.     }
  564.  
  565. trimThenUpdateWindow:
  566.  
  567.     /*
  568.      * Advance tcpHdrPtr->seqNum to correspond to first data byte.
  569.      * If there's data, remove the excess to stay within window, 
  570.      * dropping the FIN if necessary.
  571.      */
  572.     tcpHdrPtr->seqNum++;
  573.     if (dataLen > tcbPtr->recv.window) {
  574.         toDrop = dataLen - tcbPtr->recv.window;
  575.         dataLen = tcbPtr->recv.window;
  576.         headerFlags &= ~NET_TCP_FIN_FLAG;
  577.         stats.tcp.recv.packAfterWin++;
  578.         stats.tcp.recv.byteAfterWin += toDrop;
  579.     }
  580.     tcbPtr->send.updateSeqNum = tcpHdrPtr->seqNum - 1;
  581.     tcbPtr->recv.urgentPtr = tcpHdrPtr->seqNum;
  582.     goto updateWindow;
  583.     }
  584.  
  585.     /*
  586.      * p. 69
  587.      *
  588.      * Processing for states other than LISTEN or SYN_SENT.
  589.      * First check that at least some bytes of the segment are within 
  590.      * the receive window.  If the segment begins before recv.next,
  591.      * drop leading data (and SYN); if nothing is left, just ack.
  592.      */
  593.  
  594.     toDrop = tcbPtr->recv.next - tcpHdrPtr->seqNum;
  595.     if (toDrop > 0) {
  596.     if (headerFlags & NET_TCP_SYN_FLAG) {
  597.         headerFlags &= ~NET_TCP_SYN_FLAG;
  598.         tcpHdrPtr->seqNum++;
  599.  
  600.         if (tcpHdrPtr->urgentOffset > 1) {
  601.         tcpHdrPtr->urgentOffset--;
  602.         } else {
  603.         headerFlags &= ~NET_TCP_URG_FLAG;
  604.         }
  605.         toDrop--;
  606.     }
  607.  
  608.     /*
  609.      * If we need to drop more data than what's in the segment, then
  610.      * drop the segment after ACKing it.
  611.      */
  612.     if ((toDrop > dataLen) ||
  613.         ((toDrop == dataLen) && ((headerFlags & NET_TCP_FIN_FLAG) == 0))) {
  614.  
  615.         stats.tcp.recv.dupPack++;
  616.         stats.tcp.recv.dupByte += dataLen;
  617.         /*
  618.          * If the segment is just one to the left of the window,
  619.          * check two special cases:
  620.          * 1. Don't toss RST in response to 4.2-style keepalive.
  621.          * 2. If the only thing to drop is a FIN, we can drop
  622.          *    it, but check the ACK or we will get into FIN
  623.          *    wars if our FINs crossed (both CLOSING).
  624.          * In either case, send an ACK to resynchronize,
  625.          * but keep on processing for RST or ACK.
  626.          */
  627.  
  628.         if (((headerFlags & NET_TCP_FIN_FLAG) && (toDrop == dataLen+1)) 
  629. #ifdef TCP_COMPAT_42
  630.           || ((headerFlags & NET_TCP_RST_FLAG) && 
  631.             (tcpHdrPpr->sequm == tcbPtr->recv.next -1))
  632. #endif TCP_COMPAT_42
  633.         ) {
  634.         toDrop = dataLen;
  635.         headerFlags &= ~NET_TCP_FIN_FLAG;
  636.         tcbPtr->flags |= TCP_ACK_NOW;
  637.         } else {
  638.         goto dropAfterAck;
  639.         }
  640.     } else {
  641.         stats.tcp.recv.partDupPack++;
  642.         stats.tcp.recv.partDupByte += toDrop;
  643.     }
  644.  
  645.     /*
  646.      * Drop data from the front of the segment. This is done by adjusting
  647.      * the start of the data buffer pointer and length. Since the urgent
  648.      * pointer is relative to the segment seqNum, it must be adjusted or
  649.      * cleared.
  650.      */
  651.     tcpHdrPtr->seqNum += toDrop;
  652.     dataLen          -= toDrop;
  653.     data          += toDrop;
  654.  
  655.     if (tcpHdrPtr->urgentOffset > toDrop) {
  656.         tcpHdrPtr->urgentOffset -= toDrop;
  657.     } else {
  658.         headerFlags &= ~NET_TCP_URG_FLAG;
  659.         tcpHdrPtr->urgentOffset = 0;
  660.     }
  661.     }
  662.  
  663.     /*
  664.      *
  665.      * If new data are received on a connection after the
  666.      * user processes are gone, then RESET the other end.
  667.      */
  668.  
  669.     if (!Sock_HasUsers(sockPtr) && 
  670.         TCP_HAVE_SENT_FIN(tcbPtr->state) &&    (dataLen > 0)) {
  671.  
  672.     TCPCloseConnection(sockPtr, tcbPtr);
  673.     sockPtr = NULL;
  674.     tcbPtr = NULL;
  675.     stats.tcp.recv.afterClose++;
  676.     goto dropWithReset;
  677.     }
  678.  
  679.     /*
  680.      * If the segment ends after the window, drop trailing data (and
  681.      * PUSH and FIN bits, too). If there's no data left, then just ACK.
  682.      */
  683.  
  684.     toDrop = (tcpHdrPtr->seqNum + dataLen) - 
  685.                 (tcbPtr->recv.next + tcbPtr->recv.window);
  686.     if (toDrop > 0) {
  687.     stats.tcp.recv.packAfterWin++;
  688.     if (toDrop >= dataLen) {
  689.         stats.tcp.recv.byteAfterWin += dataLen;
  690.         /*
  691.          * If a new connection request is received while in the 
  692.          * TIME_WAIT state, drop the old connection and start over 
  693.          * if the sequence numbers are above the previous ones.
  694.          */
  695.         if ((headerFlags & NET_TCP_SYN_FLAG) &&
  696.         (tcbPtr->state == TIME_WAIT) &&
  697.         TCP_SEQ_GT(tcpHdrPtr->seqNum, tcbPtr->recv.next)) {
  698.  
  699.         iss = tcbPtr->recv.next + TCP_INIT_SEND_SEQ_INCR ;
  700.         TCPCloseConnection(sockPtr, tcbPtr);
  701.         goto findSock;
  702.         }
  703.         /*
  704.          * If window is closed can only take segments at
  705.          * window edge, and have to drop data and PUSH from
  706.          * incoming segments.  Continue processing, but
  707.          * remember to ack.  Otherwise, drop segment
  708.          * and ack.
  709.          */
  710.         if ((tcbPtr->recv.window == 0) && 
  711.         (tcpHdrPtr->seqNum == tcbPtr->recv.next)) {
  712.         stats.tcp.recv.winProbe++;
  713.         tcbPtr->flags |= TCP_ACK_NOW;
  714.         } else {
  715.         goto dropAfterAck;
  716.         }
  717.     } else {
  718.         stats.tcp.recv.byteAfterWin += toDrop;
  719.     }
  720.     dataLen -= toDrop;
  721.     headerFlags &= ~(NET_TCP_PSH_FLAG|NET_TCP_FIN_FLAG);
  722.     }
  723.  
  724.     /*
  725.      * p. 70
  726.      *
  727.      * Step 2: Check the RESET bit.
  728.      *
  729.      *
  730.      * If the RESET bit is set, and the tcb is in the 
  731.      *   a) SYN_RECEIVED state:
  732.      *        If passive open, return to LISTEN state.
  733.      *        If active open, inform the user that the connection was refused.
  734.      *   b) ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT states:
  735.      *        Inform the user that the connection was reset, and close 
  736.      *        the tcb.
  737.      *   c) CLOSING, LAST_ACK, TIME_WAIT states:
  738.      *        Close the tcb.
  739.      */
  740.  
  741.     if (headerFlags & NET_TCP_RST_FLAG) {
  742.     switch (tcbPtr->state) {
  743.  
  744.         case SYN_RECEIVED:
  745.         TCPDropConnection(sockPtr, tcbPtr, 
  746.                     (ReturnStatus)NET_CONNECT_REFUSED);
  747.         tcbPtr = NULL;
  748.         goto drop;
  749.  
  750.         case ESTABLISHED:
  751.         case FIN_WAIT_1:
  752.         case FIN_WAIT_2:
  753.         case CLOSE_WAIT:
  754.         TCPDropConnection(sockPtr, tcbPtr, 
  755.                 (ReturnStatus)NET_CONNECTION_RESET);
  756.         tcbPtr = NULL;
  757.         goto drop;
  758.  
  759.         case CLOSING:
  760.         case LAST_ACK:
  761.         case TIME_WAIT:
  762.         TCPCloseConnection(sockPtr, tcbPtr);
  763.         tcbPtr = NULL;
  764.         goto drop;
  765.     }
  766.     }
  767.  
  768.     /*
  769.      * p. 71
  770.      *
  771.      * Step 3: check security and precedence.
  772.      *
  773.      * (not implemented.)
  774.      *
  775.      */
  776.  
  777.     /*
  778.      * p. 71
  779.      *
  780.      * State 4: check the SYN bit.
  781.      *
  782.      * If the SYN is in the window, it is an error so send a RESET and
  783.      * drop the connection.
  784.      */
  785.     if (headerFlags & NET_TCP_SYN_FLAG) {
  786.     TCPDropConnection(sockPtr, 
  787.             tcbPtr, (ReturnStatus)NET_CONNECTION_RESET);
  788.     tcbPtr = NULL;
  789.     goto dropWithReset;
  790.     }
  791.  
  792.     /*
  793.      * p. 72
  794.      *
  795.      * Step 5: check the ACK bit.
  796.      *
  797.      * If the ACK bit is off, we drop the segment and return.
  798.      */
  799.  
  800.     if ((headerFlags & NET_TCP_ACK_FLAG) == 0) {
  801.     goto drop;
  802.     }
  803.     
  804.     switch (tcbPtr->state) {
  805.  
  806.     /*
  807.      * In the SYN_RECEIVED state, if the ACK acknowledges our SYN 
  808.      * then we enter the ESTABLISHED state and continue processing, 
  809.      * otherwise we send an RESET.
  810.      */
  811.  
  812.     case SYN_RECEIVED:
  813.  
  814.         if (TCP_SEQ_GT(tcbPtr->send.unAck, tcpHdrPtr->ackNum) ||
  815.         TCP_SEQ_GT(tcpHdrPtr->ackNum, tcbPtr->send.maxSent)) {
  816.         goto dropWithReset;
  817.         }
  818.         stats.tcp.connects++;
  819.         Sock_Connected(sockPtr);
  820.         tcbPtr->state = ESTABLISHED;
  821.         tcbPtr->maxSegSize= MIN(tcbPtr->maxSegSize, 
  822.                     TCPCalcMaxSegSize(tcbPtr));
  823.         packetPtr->data = data;
  824.         packetPtr->dataLen = dataLen;
  825.         (void) Reassemble(sockPtr, tcbPtr, (Net_TCPHeader *)NULL, 
  826.                 packetPtr);
  827.         tcbPtr->send.updateSeqNum = tcpHdrPtr->seqNum - 1;
  828.  
  829.         /* Fall into ... */
  830.  
  831.     /*
  832.      * In the ESTABLISHED state, ignore duplicate and out-of-range ACKs.
  833.      * If the ack is in the range:
  834.      *
  835.      *     tcbPtr->send.unAck < tcpHdrPtr->ackNum <= tcbPtr->send.maxSent
  836.      *
  837.      * then advance tcbPtr->send.unAck to tcpHdrPtr->ackNum and drop
  838.      * data from the retransmission queue.  If this ACK reflects
  839.      * more up-to-date window information, we update our window information.
  840.      */
  841.  
  842.     case ESTABLISHED:
  843.     case FIN_WAIT_1:
  844.     case FIN_WAIT_2:
  845.     case CLOSE_WAIT:
  846.     case CLOSING:
  847.     case LAST_ACK:
  848.     case TIME_WAIT:
  849.  
  850.         if (TCP_SEQ_LE(tcpHdrPtr->ackNum, tcbPtr->send.unAck)) {
  851.         if (dataLen == 0 && tcpHdrPtr->window == tcbPtr->send.window) {
  852.             stats.tcp.recv.dupAck++;
  853.  
  854.             /*
  855.              * If we have outstanding data (not a window probe), or
  856.              * this is a completely duplicate ack (i.e., window info
  857.              * didn't change), the ack is the biggest we've seen
  858.              * and we've seen exactly our rexmt threshhold of
  859.              * them, assume a packet has been dropped and
  860.              * retransmit it.  Kludge send.next & the congestion
  861.              * window so we send only this one packet.  If this packet 
  862.              * fills the only hole in the receiver's seq. space, the 
  863.              * next real ACK will fully open our window. This means we
  864.              * have to do the usual slow-start to not overwhelm an
  865.              * intermediate gateway with a burst of packets.  Leave
  866.              * here with the congestion window set to allow 2 packets
  867.              * on the next real ACK and the exp-to-linear thresh
  868.              * set for half the current window size (since we know
  869.              * we're losing at the current window size).
  870.              */
  871.             if ((tcbPtr->timer[TCP_TIMER_REXMT] == 0) ||
  872.             (tcpHdrPtr->ackNum != tcbPtr->send.unAck)) {
  873.             tcbPtr->dupAcks = 0;
  874.             } else {
  875.             tcbPtr->dupAcks++;
  876.             if (tcbPtr->dupAcks == tcpReXmtThresh) {
  877.                 TCPSeqNum oldNext;
  878.                 unsigned int win;
  879.  
  880.                 oldNext = tcbPtr->send.next;
  881.                 win = 
  882.                    MIN(tcbPtr->send.window, tcbPtr->send.congWindow)
  883.                 / 2 / tcbPtr->maxSegSize;
  884.  
  885.                 if (win < 2) {
  886.                 win = 2;
  887.                 }
  888.                 tcbPtr->send.cwSizeThresh = 
  889.                     win * tcbPtr->maxSegSize;
  890.  
  891.                 tcbPtr->timer[TCP_TIMER_REXMT] = 0;
  892.                 tcbPtr->rtt = 0;
  893.                 tcbPtr->send.next = tcpHdrPtr->ackNum;
  894.                 tcbPtr->send.congWindow = tcbPtr->maxSegSize;
  895.                 (void) TCPOutput(sockPtr, 
  896.                                 tcbPtr);
  897.  
  898.                 if (TCP_SEQ_GT(oldNext, tcbPtr->send.next)) {
  899.                 tcbPtr->send.next = oldNext;
  900.                 }
  901.                 goto drop;
  902.             }
  903.             }
  904.         } else {
  905.             tcbPtr->dupAcks = 0;
  906.         }
  907.         break;
  908.         }
  909.         tcbPtr->dupAcks = 0;
  910.         if (TCP_SEQ_GT(tcpHdrPtr->ackNum, tcbPtr->send.maxSent)) {
  911.         stats.tcp.recv.ackTooMuch++;
  912.         goto dropAfterAck;
  913.         }
  914.         acked = tcpHdrPtr->ackNum - tcbPtr->send.unAck;
  915.         stats.tcp.recv.ackPack++;
  916.         stats.tcp.recv.ackByte += acked;
  917.  
  918.         /*
  919.          * If the transmit timer is running and the timed sequence
  920.          * number was ACKed, update the smoothed round trip time.
  921.          * Since we now have an rtt measurement, cancel the timer
  922.          * backoff (c.f., Phil Karn's retransmit alg.). Recompute
  923.          * the initial retransmit timer.
  924.          */
  925.         if ((tcbPtr->rtt != 0) && 
  926.         TCP_SEQ_GT(tcpHdrPtr->ackNum, tcbPtr->rtseq)) {
  927.  
  928.         stats.tcp.rttUpdated++;
  929.  
  930.         if (tcbPtr->srtt != 0) {
  931.             register int delta;
  932.  
  933.             /*
  934.              * The smoothed rtt is stored as fixed point with 3 bits
  935.              * after the binary point (i.e., scaled by 8).
  936.              * The following magic is equivalentto the smoothing 
  937.              * algorithm in RFC793 with an alpha of .875
  938.              *    srtt = rtt/8 + srtt*7/8 
  939.              * (in fixed point). Adjust the round-trip time to the
  940.              * origin of 0.
  941.              */
  942.  
  943.             delta = tcbPtr->rtt - 1 - (tcbPtr->srtt >>3);
  944.             tcbPtr->srtt += delta;
  945.             if (tcbPtr->srtt <= 0) {
  946.             tcbPtr->srtt = 1;
  947.             }
  948.             /*
  949.              * We accumulate a smoothed RTT variance (actually, a
  950.              * smoothed mean difference), then set the retransmit
  951.              * timer to smoothed RTT + 2 times the smoothed
  952.              * variance.  rttvar is stored as fixed point with 2
  953.              * bits after the binary point (scaled by 4).  The
  954.              * following is equivalent to RFC793 smoothing with an
  955.              * alpha of .75 (rttvar = rttvar*3/4 + |delta| / 4).
  956.              * This replaces RFC793's wired-in beta.
  957.              */
  958.             if (delta < 0) {
  959.             delta = -delta;
  960.             }
  961.             delta -= (tcbPtr->rttvar >> 2);
  962.             tcbPtr->rttvar += delta;
  963.             if (tcbPtr->rttvar <= 0) {
  964.             tcbPtr->rttvar = 1;
  965.             }
  966.         } else {
  967.             /* 
  968.              * No RTT measurement yet - use the unsmoothed RTT.
  969.              * Set the variance to half the RTT (so our first
  970.              * retransmit happens at 2*RTT).
  971.              */
  972.             tcbPtr->srtt = tcbPtr->rtt << 3;
  973.             tcbPtr->rttvar = tcbPtr->rtt << 1;
  974.         }
  975.         tcbPtr->rtt = 0;
  976.         tcbPtr->rxtshift = 0;
  977.         TCP_TIMER_RANGESET(tcbPtr->rxtcur, 
  978.             ((tcbPtr->srtt >> 2) + tcbPtr->rttvar) >> 1,
  979.             TCP_MIN_REXMT_TIME, TCP_MAX_REXMT_TIME);
  980.         }
  981.  
  982.         /*
  983.          * If all outstanding data is acked, stop retransmit
  984.          * timer and remember to restart (more output or persist).
  985.          * If there is more data to be acked, restart retransmit
  986.          * timer.
  987.          */
  988.         if (tcpHdrPtr->ackNum == tcbPtr->send.maxSent) {
  989.         tcbPtr->timer[TCP_TIMER_REXMT] = 0;
  990.         needOutput = TRUE;
  991.         } else if (tcbPtr->timer[TCP_TIMER_PERSIST] == 0) {
  992.         tcbPtr->timer[TCP_TIMER_REXMT] = tcbPtr->rxtcur;
  993.         }
  994.  
  995.         /*
  996.          * When new data is acked, open the congestion window.
  997.          * If the window gives us less than send.cwSizeThresh packets
  998.          * in flight, open exponentially (maxSegSize per packet).
  999.          * Otherwise open linearly (maxSegSize per window,
  1000.          * or maxSegSize^2 / congWindow per packet).
  1001.          */
  1002.         {
  1003.         unsigned int incr = tcbPtr->maxSegSize;
  1004.  
  1005.         if (tcbPtr->send.congWindow > tcbPtr->send.cwSizeThresh) {
  1006.             incr = MAX(incr * incr / tcbPtr->send.congWindow, 1);
  1007.         }
  1008.         tcbPtr->send.congWindow = 
  1009.             MIN(tcbPtr->send.congWindow + incr, NET_IP_MAX_PACKET_SIZE);
  1010.         }
  1011.         { 
  1012.         int used;
  1013.  
  1014.         used = Sock_BufSize(sockPtr, SOCK_SEND_BUF,
  1015.                         SOCK_BUF_USED);
  1016.         if (acked > used) {
  1017.             tcbPtr->send.window -= used;
  1018.             Sock_BufRemove(sockPtr, SOCK_SEND_BUF, 
  1019.                         used);
  1020.             ourFinIsAcked = TRUE;
  1021.         } else {
  1022.             Sock_BufRemove(sockPtr, SOCK_SEND_BUF,
  1023.                     acked);
  1024.             tcbPtr->send.window -= acked;
  1025.             ourFinIsAcked = FALSE;
  1026.         }
  1027.         /*
  1028.          * Wakeup the waiting writer because there's more room
  1029.          * in the buffer now.
  1030.          */
  1031.         if (ips_Debug) {
  1032.             (void) fprintf(stderr,
  1033.                 "TCP Input: window opened for writer\n");
  1034.         }
  1035.         Sock_NotifyWaiter(sockPtr, FS_WRITABLE);
  1036.         }
  1037.  
  1038.         tcbPtr->send.unAck = tcpHdrPtr->ackNum;
  1039.         if (TCP_SEQ_LT(tcbPtr->send.next, tcbPtr->send.unAck)) {
  1040.         tcbPtr->send.next = tcbPtr->send.unAck;
  1041.         }
  1042.  
  1043.         switch (tcbPtr->state) {
  1044.  
  1045.         /*
  1046.          * In the FIN_WAIT_1 state, in addition to the processing
  1047.          * for the ESTABLISHED state, if our FIN is now acknowledged
  1048.          * then enter FIN_WAIT_2.
  1049.          */
  1050.  
  1051.         case FIN_WAIT_1:
  1052.             if (ourFinIsAcked) {
  1053.  
  1054.             /*
  1055.              * If we can't receive any more data, then the
  1056.              * closing user can proceed.  Starting the timer
  1057.              * is contrary to the specification, but if we
  1058.              * don't get a FIN we'll hang forever.
  1059.              */
  1060.  
  1061.             if (Sock_IsRecvStopped(sockPtr)) {
  1062.                 Sock_Disconnected(sockPtr);
  1063.                 tcbPtr->timer[TCP_TIMER_2MSL] = tcpMaxIdle;;
  1064.             }
  1065.             tcbPtr->state = FIN_WAIT_2;
  1066.             }
  1067.             break;
  1068.  
  1069.         /*
  1070.          * In the CLOSING state, in addition to the processing for
  1071.          * the ESTABLISHED state, if the ACK acknowledges our FIN
  1072.          * then enter the TIME-WAIT state, otherwise ignore the
  1073.          * segment.
  1074.          */
  1075.         case CLOSING:
  1076.             if (ourFinIsAcked) {
  1077.             tcbPtr->state = TIME_WAIT;
  1078.             TCPCancelTimers(tcbPtr);
  1079.             tcbPtr->timer[TCP_TIMER_2MSL] = 2 * TCP_MSL_TIME;
  1080.             Sock_Disconnected(sockPtr);
  1081.             }
  1082.             break;
  1083.  
  1084.         /*
  1085.          * The only thing that can arrive in the LAST_ACK state
  1086.          * is an acknowledgment of our FIN.  If our FIN is now
  1087.          * acknowledged, delete the TCB, enter the closed state
  1088.          * and return.
  1089.          */
  1090.         case LAST_ACK:
  1091.             if (ourFinIsAcked) {
  1092.             TCPCloseConnection(sockPtr, tcbPtr);
  1093.             tcbPtr = NULL;
  1094.             }
  1095.             goto drop;
  1096.  
  1097.         /*
  1098.          * In the TIME_WAIT state, the only thing that should arrive
  1099.          * is a retransmission of the remote FIN.  Acknowledge
  1100.          * it and restart the finack timer.
  1101.          */
  1102.         case TIME_WAIT:
  1103.             tcbPtr->timer[TCP_TIMER_2MSL] = 2 * TCP_MSL_TIME;
  1104.             goto dropAfterAck;
  1105.         }
  1106.  
  1107.     default:
  1108.         break;
  1109.  
  1110.     }
  1111.  
  1112. updateWindow:
  1113.  
  1114.     /*
  1115.      * p. 72
  1116.      *
  1117.      * Update window information. Don't look at the info if the ACK is 
  1118.      * missing (TAC's send garbage on the first SYN).
  1119.      */
  1120.  
  1121.     if ((headerFlags & NET_TCP_ACK_FLAG) &&
  1122.      (TCP_SEQ_LT(tcbPtr->send.updateSeqNum, tcpHdrPtr->seqNum) ||
  1123.       tcbPtr->send.updateSeqNum == tcpHdrPtr->seqNum &&
  1124.          (TCP_SEQ_LT(tcbPtr->send.updateAckNum, tcpHdrPtr->ackNum) ||
  1125.           tcbPtr->send.updateAckNum == tcpHdrPtr->ackNum && 
  1126.           tcpHdrPtr->window > tcbPtr->send.window
  1127.          )
  1128.       )
  1129.     ) {
  1130.  
  1131.     /* 
  1132.      * Keep track of pure window updates.
  1133.      */
  1134.     if (dataLen == 0 &&
  1135.         tcbPtr->send.updateAckNum == tcpHdrPtr->ackNum && 
  1136.         tcpHdrPtr->window > tcbPtr->send.window) {
  1137.         stats.tcp.recv.winUpd++;
  1138.     }
  1139.     tcbPtr->send.window      = tcpHdrPtr->window;
  1140.     tcbPtr->send.updateSeqNum = tcpHdrPtr->seqNum;
  1141.     tcbPtr->send.updateAckNum = tcpHdrPtr->ackNum;
  1142.     if (tcbPtr->send.window > tcbPtr->send.maxWindow) {
  1143.         tcbPtr->send.maxWindow = tcbPtr->send.window;
  1144.     }
  1145.     needOutput = TRUE;
  1146.     }
  1147.  
  1148.     /*
  1149.      * p. 73
  1150.      *
  1151.      * Step 6: check the URG bit.
  1152.      *
  1153.      * Process segments with urgent data.
  1154.      */
  1155.  
  1156.     if ((headerFlags & NET_TCP_URG_FLAG) && 
  1157.     (tcpHdrPtr->urgentOffset != 0) &&
  1158.     !TCP_HAVE_RECVD_FIN(tcbPtr->state)) {
  1159.  
  1160.     /*
  1161.      * This is a kludge, but if we receive and accept random urgent
  1162.      * pointers, we'll crash in the read routine.  It's hard to
  1163.      * imagine someone actually wanting to send this much urgent data.
  1164.      */
  1165.  
  1166.     if ((tcpHdrPtr->urgentOffset + 
  1167.          Sock_BufSize(sockPtr, SOCK_RECV_BUF, 
  1168.                 SOCK_BUF_USED)) > 
  1169.         Sock_BufSize(sockPtr,
  1170.                 SOCK_RECV_BUF, SOCK_BUF_MAX_SIZE)) {
  1171.         tcpHdrPtr->urgentOffset = 0;        /* XXX */
  1172.         headerFlags &= ~NET_TCP_URG_FLAG;        /* XXX */
  1173.     } else {
  1174.  
  1175.         /*
  1176.          * If this segment advances the known urgent pointer, then
  1177.          * mark the data stream.  This should not happen in
  1178.          * CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT states since a
  1179.          * FIN has been received from the remote side.  In these
  1180.          * states, we ignore the URG.
  1181.          *
  1182.          * According to RFC1011 (Assigned Internet Protocols), the urgent
  1183.          * pointer points to the last octet of urgent data.  We
  1184.          * continue, however, to consider it to indicate the first
  1185.          * octet of data past the urgent section as the original spec
  1186.          * states.
  1187.          */
  1188.  
  1189.         if (TCP_SEQ_GT(tcpHdrPtr->seqNum + tcpHdrPtr->urgentOffset, 
  1190.                 tcbPtr->recv.urgentPtr)) {
  1191.  
  1192.         tcbPtr->recv.urgentPtr = tcpHdrPtr->seqNum + 
  1193.                          tcpHdrPtr->urgentOffset;
  1194.         
  1195.         tcbPtr->urgentBufPos = 
  1196.             Sock_BufSize(sockPtr, 
  1197.                     SOCK_RECV_BUF, SOCK_BUF_USED) + 
  1198.                 tcbPtr->recv.urgentPtr - tcbPtr->recv.next - 1;
  1199.         if (tcbPtr->urgentBufPos == 0) {
  1200.             Sock_UrgentDataNext(sockPtr);
  1201.         }
  1202.         Sock_HaveUrgentData(sockPtr);
  1203.         tcbPtr->flags &= ~(TCP_HAVE_URGENT_DATA | TCP_HAD_URGENT_DATA);
  1204.         stats.tcp.recv.urgent++;
  1205.         }
  1206.  
  1207.         /*
  1208.          * Remove urgent data from the segment so it doesn't get 
  1209.          * presented to the user in the receive buffer. (It is still 
  1210.          * reflected in the segment length for sequencing purposes.) 
  1211.          * This can happen independent of advancing the URG pointer, 
  1212.          * but if two URG's are pending at once, some urgent data may 
  1213.          * creep in... ick.
  1214.          */
  1215.  
  1216.         if ((tcpHdrPtr->urgentOffset <= dataLen) &&
  1217.         !Sock_IsOptionSet(sockPtr, 
  1218.                     NET_OPT_OOB_INLINE)) {
  1219.  
  1220.         int    urgentOffset = tcpHdrPtr->urgentOffset -1;
  1221.  
  1222.         if (urgentOffset > dataLen) {
  1223.             (void) fprintf(stderr, 
  1224.               "Warning: TCP Input: urgent data not in segment\n");
  1225.         } else {
  1226.             Address urgData = data;
  1227.             urgData          += urgentOffset;
  1228.             tcbPtr->urgentData     = *urgData;
  1229.             tcbPtr->flags     |= TCP_HAVE_URGENT_DATA;
  1230.             bcopy( urgData+1, urgData, dataLen - urgentOffset -1);
  1231.             dataLen--;
  1232.             /*
  1233.              * Make sure an ACK is sent if the packet just contained
  1234.              * urgent data. Step 7 is not done if dataLen is 0 so
  1235.              * we must set the ACK flag here.
  1236.              */
  1237.             if ((dataLen == 0) &&
  1238.             (tcpHdrPtr->seqNum == tcbPtr->recv.next)) {
  1239.             tcbPtr->recv.next++;
  1240.             tcbPtr->flags |= TCP_DELAY_ACK;
  1241.             stats.tcp.recv.urgentOnly++;
  1242.             }
  1243.         }
  1244.         }
  1245.     }
  1246.     } else {
  1247.     /*
  1248.      * If no urgent data are expected, pull receive urgent pointer 
  1249.      * along with the receive window.
  1250.      */
  1251.     if (TCP_SEQ_GT(tcbPtr->recv.next, tcbPtr->recv.urgentPtr)) {
  1252.         tcbPtr->recv.urgentPtr = tcbPtr->recv.next;
  1253.     }
  1254.     }
  1255.  
  1256.  
  1257.     /*
  1258.      * p. 74
  1259.      *
  1260.      * Step 7:  Process the segment data.
  1261.      *
  1262.      * The data is merged into the TCP sequencing queue, and acknowledgment 
  1263.      * of receipt is arranged, if necessary.  This process logically involves 
  1264.      * adjusting tcbPtr->recv.window as data is presented to the user.  If 
  1265.      * a FIN has already been received on this connection then we just ignore 
  1266.      * the data.
  1267.      */
  1268.  
  1269.     if ( ((dataLen != 0) || (headerFlags & NET_TCP_FIN_FLAG)) &&
  1270.     !TCP_HAVE_RECVD_FIN(tcbPtr->state)) {
  1271.  
  1272.     int len;
  1273.  
  1274.     /*
  1275.      * Check for the common case before calling Reassemble(): the new
  1276.      * segment is the next one to be received on an established
  1277.      * connection and the reassembly queue is empty.
  1278.      */
  1279.  
  1280.     if ((tcpHdrPtr->seqNum == tcbPtr->recv.next) &&
  1281.         List_IsEmpty(&tcbPtr->reassList) &&
  1282.         (tcbPtr->state == ESTABLISHED)) {
  1283.  
  1284.         int bytesWritten;
  1285.  
  1286.         tcbPtr->recv.next += dataLen; 
  1287.         headerFlags = tcpHdrPtr->flags & NET_TCP_FIN_FLAG; 
  1288.         stats.tcp.recv.pack++;
  1289.         stats.tcp.recv.byte += dataLen;
  1290.         if ((Sock_BufAppend(sockPtr, 
  1291.                 SOCK_RECV_BUF, FALSE, dataLen, data, 
  1292.                 packetPtr->base, (Net_InetSocketAddr *) NULL,
  1293.                 &bytesWritten) != SUCCESS)
  1294.             || (bytesWritten != dataLen)) {
  1295.         (void) fprintf(stderr, 
  1296.             "Warning: (TCP)Input: append to recv buffer failed\n");
  1297.         }
  1298.  
  1299.         if (ips_Debug) {
  1300.         (void) fprintf(stderr, 
  1301.             "TCP Input: appended %d bytes: '%.*s'\n", 
  1302.                 dataLen, MIN(dataLen, 20), data);
  1303.         }
  1304.         Sock_NotifyWaiter(sockPtr, FS_READABLE);
  1305.         tcbPtr->flags |= TCP_DELAY_ACK;
  1306.     } else {
  1307.         /*
  1308.          * ACK immediately when segments are out of order so fast 
  1309.          * retransmission can work.
  1310.          */
  1311.         tcbPtr->flags |= TCP_ACK_NOW;
  1312.         packetPtr->data = data;
  1313.         packetPtr->dataLen = dataLen;
  1314.         headerFlags = Reassemble(sockPtr, tcbPtr, tcpHdrPtr, packetPtr);
  1315.     } 
  1316.     /*
  1317.      * Don't free the packet memory when we leave this routine because
  1318.      * the packet is now on the reassembly queue or in the socket's
  1319.      * receive buffer.
  1320.      */
  1321.     freePacket = FALSE;
  1322.  
  1323.     /*
  1324.      * Note the amount of data that peer has sent into our window, 
  1325.      * in order to estimate the sender's buffer size.
  1326.      */
  1327.     len = Sock_BufSize(sockPtr, SOCK_RECV_BUF, 
  1328.             SOCK_BUF_MAX_SIZE) -
  1329.             (tcbPtr->recv.next - tcbPtr->recv.advtWindow);
  1330.     if (len > tcbPtr->recv.maxWindow) {
  1331.         tcbPtr->recv.maxWindow = len;
  1332.     }
  1333.     } else {
  1334.     headerFlags &= ~NET_TCP_FIN_FLAG;
  1335.     }
  1336.  
  1337.  
  1338.     /*
  1339.      * p. 75
  1340.      *
  1341.      * Step 8: check the FIN bit.
  1342.      *
  1343.      * If a FIN is received, ACK the FIN and let the user know that 
  1344.      * the connection is closing.
  1345.      */
  1346.  
  1347.     if (headerFlags & NET_TCP_FIN_FLAG) {
  1348.     if (!TCP_HAVE_RECVD_FIN(tcbPtr->state)) {
  1349.         Sock_StopRecv(sockPtr);
  1350.         tcbPtr->flags |= TCP_ACK_NOW;
  1351.         tcbPtr->recv.next++;
  1352.     }
  1353.     switch (tcbPtr->state) {
  1354.  
  1355.         /*
  1356.          * In the SYN_RECEIVED and ESTABLISHED states, enter the 
  1357.          * CLOSE_WAIT state.
  1358.          */
  1359.         case SYN_RECEIVED:
  1360.         case ESTABLISHED:
  1361.         tcbPtr->state = CLOSE_WAIT;
  1362.         break;
  1363.  
  1364.         /*
  1365.          * If still in the FIN_WAIT_1 state, our FIN has not been acked so
  1366.          * enter the CLOSING state.
  1367.          */
  1368.         case FIN_WAIT_1:
  1369.         tcbPtr->state = CLOSING;
  1370.         break;
  1371.  
  1372.         /*
  1373.          * In the FIN_WAIT_2 state, enter the TIME_WAIT state and start
  1374.          * the time-wait timer, turning off the other standard timers.
  1375.          */
  1376.         case FIN_WAIT_2:
  1377.         tcbPtr->state = TIME_WAIT;
  1378.         TCPCancelTimers(tcbPtr);
  1379.         tcbPtr->timer[TCP_TIMER_2MSL] = 2 * TCP_MSL_TIME;
  1380.         Sock_Disconnected(sockPtr);
  1381.         break;
  1382.  
  1383.         /*
  1384.          * In the TIME_WAIT state, restart the 2*MSL time-wait timer.
  1385.          */
  1386.         case TIME_WAIT:
  1387.         tcbPtr->timer[TCP_TIMER_2MSL] = 2 * TCP_MSL_TIME;
  1388.         break;
  1389.     }
  1390.     }
  1391.  
  1392.     if (Sock_IsOptionSet(sockPtr, NET_OPT_DEBUG)) {
  1393.     TCPTrace(TCP_TRACE_INPUT, oldState, tcbPtr, &saveHeader, dataLen);
  1394.     }
  1395.  
  1396.     /*
  1397.      * Return any desired output.
  1398.      */
  1399.     if (needOutput || (tcbPtr->flags & TCP_ACK_NOW)) {
  1400.     (void) TCPOutput(sockPtr, tcbPtr);
  1401.     }
  1402.  
  1403.     if (freePacket) {
  1404.     free(packetPtr->base);
  1405.     }
  1406.     return;
  1407.  
  1408.  
  1409. dropAfterAck:
  1410.  
  1411.     /*
  1412.      * Generate an ACK dropping incoming segment if it occupies
  1413.      * sequence space, where the ACK reflects our state.
  1414.      */
  1415.     if (headerFlags & NET_TCP_RST_FLAG) {
  1416.     goto drop;
  1417.     }
  1418.     if (Sock_IsOptionSet(sockPtr, NET_OPT_DEBUG)) {
  1419.     TCPTrace(TCP_TRACE_RESPOND, oldState, tcbPtr, &saveHeader, dataLen);
  1420.     }
  1421.     TCPRespond(sockPtr, tcpHdrPtr, ipHdrPtr, 
  1422.             tcbPtr->recv.next, tcbPtr->send.next, NET_TCP_ACK_FLAG);
  1423.     free(packetPtr->base);
  1424.     return;
  1425.  
  1426.  
  1427. dropWithReset:
  1428.  
  1429.     /*
  1430.      * Generate a RESET, dropping incoming segment.
  1431.      * Make ACK acceptable to originator of segment.
  1432.      * Don't bother to respond if destination was broadcast.
  1433.      */
  1434.  
  1435.     if ((headerFlags & NET_TCP_RST_FLAG) || 
  1436.     Rte_IsBroadcastAddr(ipHdrPtr->dest)) {
  1437.     goto drop;
  1438.     }
  1439.     if (headerFlags & NET_TCP_ACK_FLAG) {
  1440.     TCPRespond(sockPtr,
  1441.                tcpHdrPtr, ipHdrPtr, (TCPSeqNum)0, 
  1442.             tcpHdrPtr->ackNum, NET_TCP_RST_FLAG);
  1443.     } else {
  1444.     if (headerFlags & NET_TCP_SYN_FLAG) {
  1445.         dataLen++;
  1446.     }
  1447.     TCPRespond(sockPtr, tcpHdrPtr, ipHdrPtr,  
  1448.             tcpHdrPtr->seqNum + dataLen, 
  1449.             (TCPSeqNum)0, NET_TCP_RST_FLAG|NET_TCP_ACK_FLAG);
  1450.     }
  1451.     free(packetPtr->base);
  1452.     return;
  1453.  
  1454.  
  1455. drop:
  1456.  
  1457.     /*
  1458.      * Drop space held by incoming segment and return.
  1459.      */
  1460.  
  1461.     if ((tcbPtr != NULL) && 
  1462.     (sockPtr != NULL) && 
  1463.     Sock_IsOptionSet(sockPtr, NET_OPT_DEBUG)) {
  1464.     TCPTrace(TCP_TRACE_DROP, oldState, tcbPtr, &saveHeader, dataLen);
  1465.     }
  1466.     free(packetPtr->base);
  1467.     return;
  1468. }
  1469.  
  1470.  
  1471.  
  1472. /*
  1473.  *----------------------------------------------------------------------
  1474.  *
  1475.  * CalcFreeSpace --
  1476.  *
  1477.  *    Calculate amount of space in the receive window.
  1478.  *    The Receive window is amount of space in the receive queue,
  1479.  *    but not less than the advertised window.
  1480.  *
  1481.  * Results:
  1482.  *    None.
  1483.  *
  1484.  * Side effects:
  1485.  *    None.
  1486.  *
  1487.  *----------------------------------------------------------------------
  1488.  */
  1489.  
  1490. static void
  1491. CalcFreeSpace(sockPtr, tcbPtr)
  1492.     Sock_InfoPtr    sockPtr;
  1493.     TCPControlBlock     *tcbPtr;
  1494. {
  1495.     int win;
  1496.  
  1497.     win = Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_FREE);
  1498.     if (win < 0) { 
  1499.     win = 0;
  1500.     }
  1501.     tcbPtr->recv.window = 
  1502.         MAX(win, (int)(tcbPtr->recv.advtWindow - tcbPtr->recv.next));
  1503. }
  1504.  
  1505.  
  1506. /*
  1507.  *----------------------------------------------------------------------
  1508.  *
  1509.  * ProcessOptions --
  1510.  *
  1511.  *    Decode the options that follow the TCP header.
  1512.  *    There is currently just one option: the maximum segment size.
  1513.  *
  1514.  * Results:
  1515.  *    None.
  1516.  *
  1517.  * Side effects:
  1518.  *    The maximum segment size of the tcb is updated.
  1519.  *
  1520.  *----------------------------------------------------------------------
  1521.  */
  1522.  
  1523. static void
  1524. ProcessOptions(len, tcpHdrPtr, tcbPtr)
  1525.     int            len;        /* Length of the TCP basic header 
  1526.                      * and options. */
  1527.     Net_TCPHeader    *tcpHdrPtr;    /* Ptr to start of the TCP header. */
  1528.     TCPControlBlock    *tcbPtr;    /* The TCB to be updated. */
  1529. {
  1530.     register unsigned char *cp;
  1531.     int option;
  1532.     int optionLen;
  1533.     int maxSegSize;
  1534.  
  1535.     cp = (unsigned char *) tcpHdrPtr;
  1536.     
  1537.     for (len -= sizeof(Net_TCPHeader); len > 0; 
  1538.      len -= optionLen, cp += optionLen) {
  1539.  
  1540.     option = cp[0];
  1541.     if (option == NET_TCP_OPTION_EOL) {
  1542.         break;
  1543.     }
  1544.     if (option == NET_TCP_OPTION_NOP) {
  1545.         optionLen = 1;
  1546.     } else {
  1547.         optionLen = cp[1];
  1548.         if (optionLen <= 0) {
  1549.         break;
  1550.         }
  1551.     }
  1552.     switch (option) {
  1553.  
  1554.         case NET_TCP_OPTION_MAX_SEG_SIZE:
  1555.         if (optionLen != 4) {
  1556.             continue;
  1557.         }
  1558.         if (!(tcpHdrPtr->flags & NET_TCP_SYN_FLAG)) {
  1559.             continue;
  1560.         }
  1561.         maxSegSize = Net_NetToHostShort(*(unsigned short *)(cp + 2));
  1562.         tcbPtr->maxSegSize = MIN(maxSegSize, TCPCalcMaxSegSize(tcbPtr));
  1563.         break;
  1564.  
  1565.         default:
  1566.             break;
  1567.  
  1568.     }
  1569.     }
  1570. }
  1571.  
  1572.  
  1573. /*
  1574.  *----------------------------------------------------------------------
  1575.  *
  1576.  * TCPCalcMaxSegSize --
  1577.  *
  1578.  *    Determines a reasonable value for the maximum segment size.
  1579.  *    The value depends on the route to the remote peer.  If
  1580.  *    the peer is on the local net, we output a size based on the
  1581.  *    maximum size on the local net.  (This includes other subnets on
  1582.  *    our net -- see Rte_IsLocal.)  If the peer is remote, return
  1583.  *    TCP_MAX_SEG_SIZE, which is on the order of 500 bytes and should
  1584.  *    never need to be fragmented by another IP server.
  1585.  *
  1586.  * Results:
  1587.  *    The maximum segment size is returned.
  1588.  *
  1589.  * Side effects:
  1590.  *    None.
  1591.  *
  1592.  *----------------------------------------------------------------------
  1593.  */
  1594.  
  1595. /*ARGSUSED*/
  1596. int
  1597. TCPCalcMaxSegSize(tcbPtr)
  1598.     TCPControlBlock *tcbPtr;
  1599. {
  1600.     register Net_IPHeader *ipHdrPtr;
  1601.     Rte_NetID        netID;
  1602.     int localOutSize;
  1603.     int maxOutSize = TCP_MAX_SEG_SIZE;
  1604.     int subnet;
  1605.  
  1606.     ipHdrPtr = tcbPtr->IPTemplatePtr;
  1607.     if (ipHdrPtr != ((Net_IPHeader *) NULL)) {
  1608.     if (!Rte_FindOutputNet(ipHdrPtr->dest,  &netID, &localOutSize)) {
  1609.         return(TCP_MAX_SEG_SIZE);
  1610.     }
  1611.     maxOutSize = localOutSize - sizeof(Net_TCPHeader) -
  1612.         sizeof(Net_IPHeader);
  1613.     if (Rte_IsLocalAddr(netID)) {
  1614. #ifdef DEBUG_SIZE
  1615.         (void) fprintf(stderr,
  1616.                "TCPCalcMaxSegSize: host is local, size %d\n",
  1617.                maxOutSize);
  1618. #endif
  1619.         return(maxOutSize);
  1620.     }
  1621.     maxOutSize = MIN(maxOutSize, TCP_MAX_SEG_SIZE);
  1622.     tcbPtr->send.congWindow = maxOutSize;
  1623. #ifdef DEBUG_SIZE
  1624.         (void) fprintf(stderr,
  1625.                "TCPCalcMaxSegSize: host is remote, size %d\n",
  1626.                maxOutSize);
  1627. #endif
  1628.     } else {
  1629. #ifdef DEBUG_SIZE
  1630.     (void) fprintf(stderr,
  1631.                "TCPCalcMaxSegSize: no ipHdrPtr\n");
  1632. #endif
  1633.     }    
  1634.     return (maxOutSize);
  1635. }
  1636.  
  1637.  
  1638.  
  1639.  
  1640. /*
  1641.  *----------------------------------------------------------------------
  1642.  *
  1643.  * Reassemble --
  1644.  *
  1645.  *    Reassembles out-of-order data segments for a TCB.
  1646.  *
  1647.  * Results:
  1648.  *    If not 0, the TCP header flags of the reassembled data.
  1649.  *
  1650.  * Side effects:
  1651.  *    Data may be appended to the socket's receive buffer.
  1652.  *
  1653.  *----------------------------------------------------------------------
  1654.  */
  1655.  
  1656. static unsigned short
  1657. Reassemble(sockPtr, tcbPtr, tcpHdrPtr, packetPtr)
  1658.     Sock_InfoPtr        sockPtr;    /* Socket of interest. */
  1659.     TCPControlBlock         *tcbPtr;    /* TCB for the socket. */
  1660.     register Net_TCPHeader    *tcpHdrPtr;    /* Header of the incoming 
  1661.                          * packet. */
  1662.     register IPS_Packet        *packetPtr;    /* Descriptor of the incoming
  1663.                          * packet. */
  1664. {
  1665.     register ReassElement    *reassPtr;
  1666.     ReassElement    *tempPtr;
  1667.     unsigned short    flags;
  1668.     Boolean        notifyNeeded;
  1669.     List_Links        *listPtr;
  1670.     register int    dataLen;
  1671.  
  1672.     listPtr = &tcbPtr->reassList;
  1673.     dataLen = packetPtr->dataLen;
  1674.  
  1675.     /*
  1676.      * If we're called with tcpHdrPtr == NULL after entering the ESTABLISHED 
  1677.      * state, then force pre-ESTABLISHED data up to user socket.
  1678.      */
  1679.  
  1680.     if (tcpHdrPtr != (Net_TCPHeader *) NULL) {
  1681.  
  1682.     /*
  1683.      * Find a segment which begins after this one does
  1684.      * (the sequence # will be greater than the seq. # of the new
  1685.      * segment).
  1686.      */
  1687.     LIST_FORALL(listPtr, (List_Links *)reassPtr) {
  1688.         if (TCP_SEQ_GT(reassPtr->seqNum, tcpHdrPtr->seqNum)) {
  1689.         break;
  1690.         }
  1691.     }
  1692.  
  1693.     /*
  1694.      * If there is a preceding segment, it may provide some of
  1695.      * our data already.  If so, drop the data from the incoming
  1696.      * segment.  If the preceding segment provides all of our data, 
  1697.      * drop the new segment.
  1698.      *
  1699.      * reassPtr now points to the next segment or the end of the list.
  1700.      * If there is a previous segment, the List_Prev of reassPtr should
  1701.      * not be the end of the list.
  1702.      */
  1703.     if (!List_IsAtEnd(listPtr, List_Prev((List_Links *)reassPtr))) {
  1704.         register int i;
  1705.  
  1706.         reassPtr = (ReassElement *) List_Prev((List_Links *)reassPtr);
  1707.  
  1708.         /*
  1709.          * Check for overlap of new and old data:
  1710.          *
  1711.          *              new s#
  1712.          *           i: |--|--|
  1713.          *               + 0 -
  1714.          *
  1715.          *     +--- old ---+
  1716.          *    seq#       s#+len
  1717.          *
  1718.          * If i is positive, then the new segment overlaps with
  1719.          * the old. If it's 0 or negative then there's no overlap.
  1720.          */
  1721.  
  1722.         /* conversion to int (in i) handles seq wraparound */
  1723.         i = (reassPtr->seqNum + reassPtr->len) - tcpHdrPtr->seqNum;
  1724.  
  1725.         if (i > 0) {
  1726.         /*
  1727.          * Overlap. If i is greater than the length of the new
  1728.          * segment, then the old segment completely overlaps
  1729.          * the new one so it duplicates data and it can be dropped.
  1730.          */
  1731.         if (i >= dataLen) {
  1732.             stats.tcp.recv.dupPack++;
  1733.             stats.tcp.recv.dupByte += dataLen;
  1734.             free(packetPtr->base);
  1735.             return(0);
  1736.         }
  1737.         /*
  1738.          * Partial overlap. Trim data from the end of the new segment.
  1739.          */
  1740.         dataLen        -= i;
  1741.         packetPtr->data    += i;
  1742.         tcpHdrPtr->seqNum += i;
  1743.         }
  1744.         reassPtr = (ReassElement *) List_Next((List_Links *)reassPtr);
  1745.     }
  1746.     stats.tcp.recv.ooPack++;
  1747.     stats.tcp.recv.ooByte += dataLen;
  1748.  
  1749.     /*
  1750.      * Now see if the new segment overlaps succeeding segments.
  1751.      * If so, then trim or delete the old ones.
  1752.      */
  1753.     while (!List_IsAtEnd(listPtr, (List_Links *)reassPtr)) {
  1754.         register int i;
  1755.  
  1756.         /*
  1757.          * Determine how much overlap there is. If i is 0 or negative
  1758.          * then, there's no overlap. If i is greater than the length
  1759.          * of the old segment, then the new segment completely covers it.
  1760.          */
  1761.         i = (tcpHdrPtr->seqNum + dataLen) - reassPtr->seqNum;
  1762.         if (i <= 0) {
  1763.         break;
  1764.         }
  1765.         if (i < reassPtr->len) {
  1766.         /*
  1767.          * Partial overlap. Trim data from the front of the old segment.
  1768.          */
  1769.         reassPtr->seqNum += i;
  1770.         reassPtr->len    -= i;
  1771.         reassPtr->data    += i;
  1772.         break;
  1773.         }
  1774.         /*
  1775.          * Complete overlap. Remove the old segment.
  1776.          */
  1777.         tempPtr = (ReassElement *)List_Next((List_Links *)reassPtr);
  1778.         List_Remove((List_Links *)reassPtr);
  1779.         free(reassPtr->base);
  1780.         free((char *) reassPtr);
  1781.         reassPtr = tempPtr;
  1782.     }
  1783.  
  1784.     /*
  1785.      * Stick new segment in its place.
  1786.      */
  1787.     tempPtr = (ReassElement *) malloc(sizeof(ReassElement));
  1788.     List_InitElement((List_Links *) tempPtr);
  1789.     tempPtr->len = dataLen;
  1790.     tempPtr->data = packetPtr->data;
  1791.     tempPtr->base = packetPtr->base;
  1792.     tempPtr->seqNum = tcpHdrPtr->seqNum;
  1793.     tempPtr->flags = tcpHdrPtr->flags;
  1794.     List_Insert((List_Links *)tempPtr, LIST_BEFORE((List_Links *)reassPtr));
  1795.     }
  1796.  
  1797.     /*
  1798.      * Go through the reassembly queue and append the first contigous chunk 
  1799.      * of the segment to the socket receive buffer. Stop when a gap is found
  1800.      * or the end of the list is reached.
  1801.      */
  1802.  
  1803.     if (!TCP_HAVE_RECVD_SYN(tcbPtr->state)) {
  1804.     return(0);
  1805.     }
  1806.     reassPtr = (ReassElement *) List_First(listPtr);
  1807.     if (List_IsAtEnd(listPtr, (List_Links *)reassPtr) ||
  1808.     (reassPtr->seqNum != tcbPtr->recv.next)) {
  1809.     return(0);
  1810.     }
  1811.     if ((tcbPtr->state == SYN_RECEIVED) && (dataLen != 0)) {
  1812.     return(0);
  1813.     }
  1814.  
  1815.     notifyNeeded = FALSE;
  1816.     do {
  1817.     tcbPtr->recv.next += reassPtr->len;
  1818.     flags = reassPtr->flags & NET_TCP_FIN_FLAG;
  1819.     tempPtr = (ReassElement *)List_Next((List_Links *) reassPtr);
  1820.     List_Remove((List_Links *)reassPtr);
  1821.     if (Sock_IsRecvStopped(sockPtr)) {
  1822.         free(reassPtr->base);
  1823.     } else {
  1824.         int amt;
  1825.  
  1826.         if ((Sock_BufAppend(sockPtr,
  1827.                 SOCK_RECV_BUF, FALSE, reassPtr->len,
  1828.                 reassPtr->data, reassPtr->base, 
  1829.                 (Net_InetSocketAddr *) NULL,
  1830.                 &amt) != SUCCESS) || (amt != reassPtr->len)) {
  1831.         if (amt == 0) {
  1832.             free(reassPtr->base);
  1833.         }
  1834.         }
  1835.         if (ips_Debug) {
  1836.         (void) fprintf(stderr, 
  1837.             "TCP Reassemble: appended %d bytes: '%.*s'\n",
  1838.                 amt, MIN(amt, 20), reassPtr->data);
  1839.                 
  1840.         }
  1841.         notifyNeeded = TRUE;
  1842.     }
  1843.     free((char *) reassPtr);
  1844.     reassPtr = tempPtr;
  1845.     } while (!List_IsAtEnd(listPtr, (List_Links *)reassPtr) && 
  1846.         (reassPtr->seqNum == tcbPtr->recv.next));
  1847.  
  1848.     if (notifyNeeded) {
  1849.     Sock_NotifyWaiter(sockPtr, FS_READABLE);
  1850.     }
  1851.     return(flags);
  1852. }
  1853.  
  1854.  
  1855. /*
  1856.  *----------------------------------------------------------------------
  1857.  *
  1858.  * TCPCleanReassList --
  1859.  *
  1860.  *    Removes all segments on the reassembly list of a TCP control block.
  1861.  *
  1862.  * Results:
  1863.  *    None.
  1864.  *
  1865.  * Side effects:
  1866.  *    Memory for the reassembly information and packets are deallocated.
  1867.  *
  1868.  *----------------------------------------------------------------------
  1869.  */
  1870.  
  1871. void
  1872. TCPCleanReassList(tcbPtr)
  1873.     TCPControlBlock     *tcbPtr;    /* TCB containing a reassembly Q. */
  1874. {
  1875.     List_Links    *ptr;
  1876.     List_Links    *tempPtr;
  1877.  
  1878.     LIST_FORALL(&tcbPtr->reassList, ptr) {
  1879.     tempPtr = List_Next(ptr);
  1880.     List_Remove(ptr);
  1881.     free((char *) ((ReassElement *)ptr)->base);
  1882.     free((char *) ptr);
  1883.     ptr = tempPtr;
  1884.     }
  1885. }
  1886. @
  1887.  
  1888.  
  1889. 1.13
  1890. log
  1891. @Fixed up debugging info.
  1892. @
  1893. text
  1894. @d27 1
  1895. a27 1
  1896. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpInput.c,v 1.12 89/05/19 14:40:24 douglis Exp Locker: nelson $ SPRITE (Berkeley)";
  1897. d1466 1
  1898. a1466 1
  1899.         case NET_TCP_MAX_SEG_SIZE:
  1900. @
  1901.  
  1902.  
  1903. 1.12
  1904. log
  1905. @return the max seg size depending on the mtu and whether it's local,
  1906. rather than fixed constant.
  1907. @
  1908. text
  1909. @d27 1
  1910. a27 1
  1911. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpInput.c,v 1.11 89/03/23 09:53:35 brent Exp Locker: douglis $ SPRITE (Berkeley)";
  1912. d222 3
  1913. d257 4
  1914. a260 2
  1915.             ipHdrPtr->dest, (tcpHdrPtr->destPort),
  1916.             ipHdrPtr->source,(tcpHdrPtr->srcPort),
  1917. @
  1918.  
  1919.  
  1920. 1.11
  1921. log
  1922. @Removed stdio.h include
  1923. @
  1924. text
  1925. @d27 1
  1926. a27 1
  1927. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/tcpInput.c,v 1.10 89/02/21 10:08:13 brent Exp $ SPRITE (Berkeley)";
  1928. d1486 11
  1929. a1496 6
  1930.  *    The value depends on the route to the remote peer.
  1931.  *
  1932.  * Results:
  1933.  *    For now, just return a resonable value.
  1934.  *
  1935.  * Side effects:
  1936. d1507 35
  1937. a1541 1
  1938.     return (TCP_MAX_SEG_SIZE);
  1939. @
  1940.  
  1941.  
  1942. 1.10
  1943. log
  1944. @Added TCP_MemBin
  1945. @
  1946. text
  1947. @d27 1
  1948. a27 1
  1949. static char rcsid[] = "$Header: /a/daemons/ipServer/RCS/tcpInput.c,v 1.9 88/10/17 09:08:28 ouster Exp $ SPRITE (Berkeley)";
  1950. a41 1
  1951. #include <stdio.h>
  1952. @
  1953.  
  1954.  
  1955. 1.9
  1956. log
  1957. @Changed not to return FS_WOULD_BLOCK on a write unless zero bytes
  1958. were transferred.
  1959. @
  1960. text
  1961. @d27 1
  1962. a27 1
  1963. static char rcsid[] = "$Header: tcpInput.c,v 1.8 88/09/22 14:29:13 mendel Exp $ SPRITE (Berkeley)";
  1964. d71 26
  1965. @
  1966.  
  1967.  
  1968. 1.8
  1969. log
  1970. @Patched bug in update of tcp round trip timer (rtt).
  1971. @
  1972. text
  1973. @d27 1
  1974. a27 1
  1975. static char rcsid[] = "$Header: tcpInput.c,v 1.7 88/09/15 09:32:56 mendel Exp $ SPRITE (Berkeley)";
  1976. d1166 2
  1977. d1172 1
  1978. a1172 1
  1979.         if (Sock_BufAppend(sockPtr, 
  1980. d1175 2
  1981. a1176 1
  1982.                 (int *) NULL) != SUCCESS) {
  1983. d1669 1
  1984. a1669 1
  1985.         if (Sock_BufAppend(sockPtr,
  1986. d1673 1
  1987. a1673 1
  1988.                 &amt) != SUCCESS) {
  1989. @
  1990.  
  1991.  
  1992. 1.7
  1993. log
  1994. @Added/removed byte swapping for SPUR.
  1995. @
  1996. text
  1997. @d27 1
  1998. a27 1
  1999. static char rcsid[] = "$Header: tcpInput.c,v 1.6 88/08/16 11:19:08 mendel Exp $ SPRITE (Berkeley)";
  2000. d843 1
  2001. a843 1
  2002.             delta -= (tcbPtr->rtt >> 2);
  2003. @
  2004.  
  2005.  
  2006. 1.6
  2007. log
  2008. @Converted to use new libc.a
  2009. @
  2010. text
  2011. @d27 1
  2012. a27 1
  2013. static char rcsid[] = "$Header: tcpInput.c,v 1.5 88/05/31 14:10:10 mendel Exp $ SPRITE (Berkeley)";
  2014. d177 1
  2015. a177 1
  2016.     pseudoHdr.len        = dataLen;
  2017. d215 1
  2018. d218 1
  2019. d229 3
  2020. a231 2
  2021.             ipHdrPtr->dest, tcpHdrPtr->destPort,
  2022.             ipHdrPtr->source, tcpHdrPtr->srcPort, ipHdrPtr->ident);
  2023. @
  2024.  
  2025.  
  2026. 1.5
  2027. log
  2028. @Corrected updating of tcbPtr->recv.next when processing out of order bytes
  2029. in Reassemble.  
  2030. @
  2031. text
  2032. @d27 1
  2033. a27 1
  2034. static char rcsid[] = "$Header: tcpInput.c,v 1.4 88/05/15 19:29:46 andrew Exp $ SPRITE (Berkeley)";
  2035. d41 2
  2036. a42 1
  2037. #include "io.h"
  2038. a43 4
  2039. #include "mem.h"
  2040. #include "list.h"
  2041. #include "sys.h"
  2042. #include "byte.h"
  2043. d58 1
  2044. a58 1
  2045.                      * is used with Mem_Free. */
  2046. d94 1
  2047. a94 1
  2048.     Io_PrintStream(io_StdErr, "TCP: sizeof(tcb) = %d\n", 
  2049. d155 1
  2050. a155 1
  2051.     Mem_Free(packetPtr->base);
  2052. d181 1
  2053. a181 1
  2054.         Io_PrintStream(io_StdErr, "TCP: checksum != 0 (%x)\n", sum);
  2055. d185 1
  2056. a185 1
  2057.         Mem_Free(packetPtr->base);
  2058. d197 1
  2059. a197 1
  2060.     Mem_Free(packetPtr->base);
  2061. d224 1
  2062. a224 1
  2063.     Io_PrintStream(io_StdErr, 
  2064. d229 2
  2065. a230 2
  2066.     TCPPrintHdrFlags(io_StdErr, headerFlags);
  2067.     Io_PrintStream(io_StdErr, "  seq=%d,  ack=%d\n",
  2068. d242 1
  2069. a242 1
  2070.     sockPtr = Sock_Match(TCP_PROTO_INDEX, 
  2071. d311 2
  2072. a312 1
  2073.     sockPtr = TCPCloneConnection(sockPtr, ipHdrPtr->dest, 
  2074. d548 2
  2075. a549 2
  2076.     if (!Sock_HasUsers(sockPtr) && TCP_HAVE_SENT_FIN(tcbPtr->state) &&
  2077.     (dataLen > 0)) {
  2078. d665 2
  2079. a666 1
  2080.     TCPDropConnection(sockPtr, tcbPtr, (ReturnStatus)NET_CONNECTION_RESET);
  2081. d774 2
  2082. a775 1
  2083.                 (void) TCPOutput(sockPtr, tcbPtr);
  2084. d893 2
  2085. a894 1
  2086.         used = Sock_BufSize(sockPtr, SOCK_SEND_BUF, SOCK_BUF_USED);
  2087. d897 2
  2088. a898 1
  2089.             Sock_BufRemove(sockPtr, SOCK_SEND_BUF, used);
  2090. d901 2
  2091. a902 1
  2092.             Sock_BufRemove(sockPtr, SOCK_SEND_BUF, acked);
  2093. d911 1
  2094. a911 1
  2095.             Io_PrintStream(io_StdErr,
  2096. d1046 4
  2097. a1049 2
  2098.          Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_USED)) > 
  2099.         Sock_BufSize(sockPtr,SOCK_RECV_BUF, SOCK_BUF_MAX_SIZE)) {
  2100. d1075 2
  2101. a1076 1
  2102.             Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_USED) + 
  2103. d1096 2
  2104. a1097 1
  2105.         !Sock_IsOptionSet(sockPtr, NET_OPT_OOB_INLINE)) {
  2106. d1102 2
  2107. a1103 2
  2108.             Sys_Panic(SYS_WARNING, 
  2109.                     "TCP Input: urgent data not in segment\n");
  2110. d1109 1
  2111. a1109 1
  2112.             Byte_Copy(dataLen - urgentOffset -1, urgData+1, urgData);
  2113. d1167 2
  2114. a1168 1
  2115.         if (Sock_BufAppend(sockPtr, SOCK_RECV_BUF, FALSE, dataLen, data, 
  2116. d1171 2
  2117. a1172 2
  2118.         Sys_Panic(SYS_WARNING, 
  2119.             "(TCP)Input: append to recv buffer failed\n");
  2120. d1176 1
  2121. a1176 1
  2122.         Io_PrintStream(io_StdErr, 
  2123. d1203 2
  2124. a1204 1
  2125.     len = Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_MAX_SIZE) -
  2126. d1280 1
  2127. a1280 1
  2128.     Mem_Free(packetPtr->base);
  2129. d1297 3
  2130. a1299 3
  2131.     TCPRespond(sockPtr, tcpHdrPtr, ipHdrPtr, tcbPtr->recv.next, 
  2132.             tcbPtr->send.next, NET_TCP_ACK_FLAG);
  2133.     Mem_Free(packetPtr->base);
  2134. d1316 2
  2135. a1317 1
  2136.     TCPRespond(sockPtr, tcpHdrPtr, ipHdrPtr, (TCPSeqNum)0, 
  2137. d1323 2
  2138. a1324 1
  2139.     TCPRespond(sockPtr, tcpHdrPtr, ipHdrPtr,  tcpHdrPtr->seqNum + dataLen, 
  2140. d1327 1
  2141. a1327 1
  2142.     Mem_Free(packetPtr->base);
  2143. d1342 1
  2144. a1342 1
  2145.     Mem_Free(packetPtr->base);
  2146. d1374 1
  2147. a1374 1
  2148.     if (win < 0) {
  2149. d1571 1
  2150. a1571 1
  2151.             Mem_Free(packetPtr->base);
  2152. d1616 2
  2153. a1617 2
  2154.         Mem_Free(reassPtr->base);
  2155.         Mem_Free((Address) reassPtr);
  2156. d1624 1
  2157. a1624 1
  2158.     tempPtr = Mem_New(ReassElement);
  2159. d1659 1
  2160. a1659 1
  2161.         Mem_Free(reassPtr->base);
  2162. d1663 2
  2163. a1664 1
  2164.         if (Sock_BufAppend(sockPtr, SOCK_RECV_BUF, FALSE, reassPtr->len,
  2165. d1669 1
  2166. a1669 1
  2167.             Mem_Free(reassPtr->base);
  2168. d1673 1
  2169. a1673 1
  2170.         Io_PrintStream(io_StdErr, 
  2171. d1680 1
  2172. a1680 1
  2173.     Mem_Free((Address) reassPtr);
  2174. d1718 2
  2175. a1719 2
  2176.     Mem_Free((Address) ((ReassElement *)ptr)->base);
  2177.     Mem_Free((Address) ptr);
  2178. @
  2179.  
  2180.  
  2181. 1.4
  2182. log
  2183. @incorporate BSD version 7.18: always ACK_NOW for out-of-order segments,
  2184. removed allowDelayack flag.
  2185. @
  2186. text
  2187. @d27 1
  2188. a27 1
  2189. static char rcsid[] = "$Header: tcpInput.c,v 6.2 88/05/15 19:15:30 andrew Exp $ SPRITE (Berkeley)";
  2190. d1643 1
  2191. a1643 1
  2192.     tcbPtr->recv.next += dataLen;
  2193. @
  2194.  
  2195.  
  2196. 1.3
  2197. log
  2198. @Fixed a typo.
  2199. @
  2200. text
  2201. @d13 1
  2202. a13 1
  2203.  *    "@@(#)tcp_input.c 7.17 (Berkeley) 3/16/88"
  2204. d27 1
  2205. a27 1
  2206. static char rcsid[] = "$Header: tcpInput.c,v 1.2 88/04/27 09:10:07 brent Exp $ SPRITE (Berkeley)";
  2207. a67 6
  2208. /*
  2209.  * A flag to indicate if packet ACKs should be delayed or not.
  2210.  * (Tuning parameter.)
  2211.  */
  2212. static Boolean allowDelayedACKs = TRUE;
  2213.  
  2214. a1110 1
  2215.  
  2216. d1112 1
  2217. a1112 5
  2218.             if (allowDelayedACKs) {
  2219.                 tcbPtr->flags |= TCP_DELAY_ACK;
  2220.             } else {
  2221.                 tcbPtr->flags |= TCP_ACK_NOW;
  2222.             }
  2223. d1173 1
  2224. d1175 5
  2225. a1189 6
  2226.  
  2227.     if (allowDelayedACKs) {
  2228.         tcbPtr->flags |= TCP_DELAY_ACK;
  2229.     } else {
  2230.         tcbPtr->flags |= TCP_ACK_NOW;
  2231.     }
  2232. @
  2233.  
  2234.  
  2235. 1.2
  2236. log
  2237. @New update with Jacobson enhancements
  2238. @
  2239. text
  2240. @d27 1
  2241. a27 1
  2242. static char rcsid[] = "$Header: tcpInput.c,v 6.1 88/04/24 23:14:42 andrew Exp $ SPRITE (Berkeley)";
  2243. d877 1
  2244. a877 1
  2245.         tcbPtr->timer[TCP_TIMER_PERSIST] = tcbPtr->rxtcur;
  2246. @
  2247.  
  2248.  
  2249. 1.1
  2250. log
  2251. @Initial revision
  2252. @
  2253. text
  2254. @d13 1
  2255. a13 1
  2256.  *    "@@(#)tcp_input.c 7.4 (Berkeley) 6/6/87"
  2257. d27 1
  2258. a27 1
  2259. static char rcsid[] = "$Header: tcpInput.c,v 6.0 87/09/08 15:56:55 andrew Stable $ SPRITE (Berkeley)";
  2260. d52 1
  2261. a52 2
  2262. float    tcpSmoothAlpha    = TCP_SMOOTH_ALPHA;
  2263. float    tcpSmoothBeta    = TCP_SMOOTH_BETA;
  2264. d150 1
  2265. d258 3
  2266. a260 1
  2267.      * all data in the incoming segment is discarded.
  2268. d270 3
  2269. a305 1
  2270.  
  2271. a308 1
  2272.  
  2273. a311 1
  2274.  
  2275. a315 1
  2276.  
  2277. d351 1
  2278. a351 1
  2279.     tcbPtr->timer[TCP_TIMER_KEEP_ALIVE] = TCP_KEEP_TIME;
  2280. d369 1
  2281. a369 1
  2282.     tcbPtr->timer[TCP_TIMER_KEEP_ALIVE] = TCP_KEEP_TIME;
  2283. d436 12
  2284. d476 3
  2285. a478 3
  2286.      * First check that at least some bytes of segment are within 
  2287.      * receive window.  If segment begins before recv.next,
  2288.      * drop leading data (and SYN); if nothing left, just ack.
  2289. d504 26
  2290. a529 1
  2291.         goto dropAfterAck;
  2292. a530 2
  2293.     stats.tcp.recv.partDupPack++;
  2294.     stats.tcp.recv.partDupByte += toDrop;
  2295. d550 5
  2296. a554 9
  2297.     if (tcbPtr->recv.window == 0) {
  2298.     /*
  2299.      * If the window is closed, we can only take segments at the
  2300.      * window edge, and we have to drop data and PUSH from
  2301.      * incoming segments.
  2302.      *
  2303.      * If new data is received on a connection after the
  2304.      * user processes are gone, then RESET the other end.
  2305.      */
  2306. d556 2
  2307. a557 3
  2308.     if (!Sock_HasUsers(sockPtr) &&
  2309.         TCP_HAVE_SENT_FIN(tcbPtr->state) &&
  2310.         (dataLen > 0)) {
  2311. d559 17
  2312. a575 8
  2313.         TCPCloseConnection(sockPtr, tcbPtr);
  2314.         sockPtr = NULL;
  2315.         tcbPtr = NULL;
  2316.         stats.tcp.recv.afterClose++;
  2317.         goto dropWithReset;
  2318.     }
  2319.     if (tcbPtr->recv.next != tcpHdrPtr->seqNum) {
  2320.         stats.tcp.recv.packAfterWin++;
  2321. d577 22
  2322. a598 4
  2323.         goto dropAfterAck;
  2324.     }
  2325.     if (dataLen > 0) {
  2326.         if (dataLen == 1) {
  2327. d600 1
  2328. a601 35
  2329.         stats.tcp.recv.packAfterWin++;
  2330.         stats.tcp.recv.byteAfterWin += dataLen;
  2331.         }
  2332.         dataLen = 0;
  2333.         headerFlags &= ~(NET_TCP_PSH_FLAG|NET_TCP_FIN_FLAG);
  2334.     }
  2335.     } else {
  2336.     /*
  2337.      * If the segment ends after the window, drop trailing data (and
  2338.      * PUSH and FIN bits, too). If there's no data left, then just ACK.
  2339.      */
  2340.  
  2341.     toDrop = (tcpHdrPtr->seqNum + dataLen) - 
  2342.                 (tcbPtr->recv.next + tcbPtr->recv.window);
  2343.     if (toDrop > 0) {
  2344.         if (toDrop >= dataLen) {
  2345.         /*
  2346.          * If a new connection request is received while in the 
  2347.          * TIME_WAIT state, drop the old connection and start over 
  2348.          * if the sequence numbers are above the previous ones.
  2349.          */
  2350.         if ((headerFlags & NET_TCP_SYN_FLAG) &&
  2351.             (tcbPtr->state == TIME_WAIT) &&
  2352.             TCP_SEQ_GT(tcpHdrPtr->seqNum, tcbPtr->recv.next)) {
  2353.  
  2354.             iss = tcbPtr->recv.next + TCP_INIT_SEND_SEQ_INCR ;
  2355.             TCPCloseConnection(sockPtr, tcbPtr);
  2356.             goto findSock;
  2357.         }
  2358.         if (toDrop == 1) {
  2359.             stats.tcp.recv.winProbe++;
  2360.         } else {
  2361.             stats.tcp.recv.packAfterWin++;
  2362.             stats.tcp.recv.byteAfterWin += dataLen;
  2363.         }
  2364. d604 1
  2365. a604 1
  2366.         stats.tcp.recv.packAfterWin++;
  2367. a605 2
  2368.         dataLen -= toDrop;
  2369.         headerFlags &= ~(NET_TCP_PSH_FLAG|NET_TCP_FIN_FLAG);
  2370. d607 2
  2371. d617 2
  2372. a618 2
  2373.      * If the RESET bit is set, and the tcb is in the
  2374.      *    SYN_RECEIVED state:
  2375. d621 1
  2376. a621 1
  2377.      *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT states:
  2378. d624 1
  2379. a624 1
  2380.      *    CLOSING, LAST_ACK, TIME_WAIT states:
  2381. a703 5
  2382.         tcbPtr->send.unAck++;            /* SYN acked */
  2383.         if (TCP_SEQ_LT(tcbPtr->send.next, tcbPtr->send.unAck)) {
  2384.         tcbPtr->send.next = tcbPtr->send.unAck;
  2385.         }
  2386.         tcbPtr->timer[TCP_TIMER_REXMT] = 0;
  2387. d737 1
  2388. a737 1
  2389.         if (dataLen == 0) {
  2390. d739 52
  2391. d794 1
  2392. d806 3
  2393. d810 2
  2394. a811 2
  2395.         if ((tcbPtr->roundTripTime != 0) && 
  2396.         TCP_SEQ_GT(tcpHdrPtr->ackNum, tcbPtr->rttSeqNum)) {
  2397. d814 37
  2398. a850 2
  2399.         if (tcbPtr->smoothRTT == 0) {
  2400.             tcbPtr->smoothRTT = tcbPtr->roundTripTime;
  2401. d852 7
  2402. a858 2
  2403.             tcbPtr->smoothRTT = tcpSmoothAlpha * tcbPtr->smoothRTT +
  2404.                 (1 - tcpSmoothAlpha) * tcbPtr->roundTripTime;
  2405. d860 5
  2406. a864 1
  2407.         tcbPtr->roundTripTime = 0;
  2408. d877 1
  2409. a877 4
  2410.         TCP_TIMER_RANGESET(tcbPtr->timer[TCP_TIMER_REXMT],
  2411.                 tcpSmoothBeta * tcbPtr->smoothRTT, 
  2412.                 TCP_MIN_REXMT_TIME, TCP_MAX_REXMT_TIME);
  2413.         tcbPtr->retransShift = 0;
  2414. d881 5
  2415. a885 2
  2416.          * When new data is acked, open the congestion window
  2417.          * by one maximum-sized segment.
  2418. d887 9
  2419. a895 2
  2420.         tcbPtr->send.congWindow = MIN(tcbPtr->send.congWindow + 
  2421.                     tcbPtr->maxSegSize, 65535);
  2422. d903 1
  2423. d907 1
  2424. a907 1
  2425.             acked = 0;
  2426. a924 1
  2427. #define    ourFinIsAcked    (acked > 0)
  2428. d945 1
  2429. a945 1
  2430.                 tcbPtr->timer[TCP_TIMER_2MSL] = TCP_MAX_IDLE_TIME;
  2431. a987 1
  2432. #undef ourFinIsAcked
  2433. a1018 1
  2434.  
  2435. a1019 1
  2436.         stats.tcp.recv.dupAck--;
  2437. @
  2438.